/* Includes ------------------------------------------------------------------*/
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
#include <stdarg.h>
#include <time.h>
#include <math.h>
#include <stdint.h>
#include "stm32f10x_usart.h"
#include "stm32f10x_dac.h"
#include "stm32f10x_rcc.h"
#include "stm32f10x_flash.h"
#include "stm32f10x_tim.h"
#include "sys.h"
#include "misc.h"

#define SYMBOL_GLOBALS
#include "common_peripheral.h"
#undef SYMBOL_GLOBALS

//#include "scp.h"

//* 这里的时钟定义最重要的是要根据实际使用的外界晶振频率进行配置，一般STM32F10x系列用8MHz或12MHz的
//* 晶振，配置RCC时要将HSE_VALUE宏的值调整至外接晶振的频率，否则像串口之类的外设就会无法正常工作
void RCCInit(void)
{
  ErrorStatus enumErrCode;

  /* RCC system reset(for debug purpose) */
  RCC_DeInit();

  //* 使能外部晶振时钟
  RCC_HSEConfig(RCC_HSE_ON);

  /* Wait till HSE is ready */
  enumErrCode = RCC_WaitForHSEStartUp();

  if (enumErrCode == SUCCESS)
  {
		/* Enable Prefetch Buffer */
		FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);
		/* Flash 2 wait state */
		FLASH_SetLatency(FLASH_Latency_2);
 
		/* HCLK = SYSCLK */
		RCC_HCLKConfig(RCC_SYSCLK_Div1); 
		/* PCLK2 = HCLK */					   
		RCC_PCLK2Config(RCC_HCLK_Div1); 	   //APB2 CLK : 72MHz
		/* PCLK1 = HCLK/2 */
		RCC_PCLK1Config(RCC_HCLK_Div2);		   //APB1 CLK ：36MHz
		
		//* 外部时钟12MHz，不分频输入，6倍频输出正好72MHz
		RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_6);
		
		//* 使能PLL,并等待PLL准备好
		RCC_PLLCmd(ENABLE);
		while (RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET);
			
		/* Select PLL as system clock source and Wait till PLL is used as system clock source */
		RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);
		while(RCC_GetSYSCLKSource() != 0x08);		
		
		//* APB1和2的相关外设时钟使能													
		RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | 
														RCC_APB2Periph_GPIOA | 
														RCC_APB2Periph_GPIOB | 
														RCC_APB2Periph_GPIOC | 
														RCC_APB2Periph_GPIOD | 
														RCC_APB2Periph_GPIOE | 
														RCC_APB2Periph_TIM1  | 
														RCC_APB2Periph_AFIO  | 0, ENABLE);
		RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2 | 
													 RCC_APB1Periph_USART3 | 
													 RCC_APB1Periph_PWR    | 
													 RCC_APB1Periph_BKP    | 0, ENABLE);
													 
		// 开启DMA1时钟
		RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
  }
  else
  { 
  		/* If HSE fails to start-up, the application will have wrong clock configuration.
       	User can add here some code to deal with this error */    

    	/* Go to infinite loop */
    	while (1);
  }
}

void ControllPinInit(void)
{
	GPIO_InitTypeDef   stInitStruct;
	
	//* 系统使用SWJ，所以屏蔽掉JTAG相关复用引脚使其恢复成普通GPIO引脚（PB3/4 PA15）
	GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE);
		
	//* 以下为输出
	//* --------------------------------------------------------------------
	//* 带上拉的输出脚
	stInitStruct.GPIO_Speed = GPIO_Speed_10MHz;
	stInitStruct.GPIO_Mode  = GPIO_Mode_Out_PP;	
	
	//*4G电源通断引脚
	stInitStruct.GPIO_Pin   = PIN_M4G_POWER;
	GPIO_Init(PORT_M4G_POWER, &stInitStruct);
	
	//* LED_RUN
	stInitStruct.GPIO_Pin   = PIN_LED_RUN;
	GPIO_Init(PORT_LED_RUN, &stInitStruct);
	
	//* LED_WARN
	stInitStruct.GPIO_Pin   = PIN_LED_WARN;
	GPIO_Init(PORT_LED_WARN, &stInitStruct);
	
	//* LED_FAULT
	stInitStruct.GPIO_Pin   = PIN_LED_FAULT;
	GPIO_Init(PORT_LED_FAULT, &stInitStruct);
}

void ExternalInterruptInit(void)
{
	NVIC_InitTypeDef   NVIC_InitStructure;
		
	EXTI_DeInit();		//* EXTI初始化

	NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0); 
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);	//* 抢占优先级：0/1  从优先级0-7

	NVIC_InitStructure.NVIC_IRQChannel = (uint8_t)SysTick_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 7;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_Init(&NVIC_InitStructure);

	/* Enable the USART2 Interrupt */
	//* ================================================================
	NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 6;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_Init(&NVIC_InitStructure);
	
	/* Enable the DMA1 Transmission Complete Interrupt For USART2 TX*/
	NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel7_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 5;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_Init(&NVIC_InitStructure);
	//* ================================================================
	
	/* Enable the USART3 Interrupt */
	//* ================================================================
	NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_Init(&NVIC_InitStructure);
	
	/* Enable the DMA1 Transmission Complete Interrupt For USART3 TX*/
	NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel2_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_Init(&NVIC_InitStructure);
	//* ================================================================
}

//* 独立看门狗初始化
void IWDGInit(uint8_t ubPrescalerID, uint32_t unTimeout) 
{
	uint32_t unPrescalerVal;
	uint32_t unReloadCnt;
	
	//* 使能对寄存器IWDG_PR和IWDG_RLR的写操作
 	IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable);
		
	//* 设置IWDG预分频值
	IWDG_SetPrescaler(IWDG_Prescaler_128); 
	
	switch(ubPrescalerID)
	{	
		case IWDG_Prescaler_4:
			unPrescalerVal = 4;
			break;
		
		case IWDG_Prescaler_8:
			unPrescalerVal = 8;
			break;
		
		case IWDG_Prescaler_16:
			unPrescalerVal = 16;
			break;
		
		case IWDG_Prescaler_32:
			unPrescalerVal = 32;
			break;
		
		case IWDG_Prescaler_64:
			unPrescalerVal = 64;
			break;
		
		case IWDG_Prescaler_128:
			unPrescalerVal = 128;
			break;
		
		case IWDG_Prescaler_256:			
		default:
			unPrescalerVal = 256;
			break;
	}
	
	unReloadCnt = (40000 / unPrescalerVal) * unTimeout;
	if(unReloadCnt > 0x0FFF)
		unReloadCnt = 0x0FFE;
	
	//* 设置IWDG重装载值
	IWDG_SetReload(unReloadCnt); 
	
	//* 按照IWDG重装载寄存器的值重装载IWDG计数器
	IWDG_ReloadCounter();
	
	//* 使能IWDG
	IWDG_Enable(); 
}

//* 喂狗
void IWDGFeed(void)
{   
 	IWDG_ReloadCounter();										   
}


